home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #5
/
Amiga Plus CD - 2000 - No. 5.iso
/
Tools
/
Dev
/
FPSE_src
/
joypad.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-01
|
7KB
|
279 lines
/*
Gamepad & memory card emulation
===============================
Written by LDChen
*/
#include "fpse.h"
#define ACKPAD sio->Delta |= DSR;
#define NACKPAD
// sio->Status &= ~DSR; sio->Delta |= DSR;
#define B13 0x2000
#define READ_CARD 0x80
#define KPAD 1
#define KMEM 2
#ifdef MSB_FIRST
#define L0 3
#define L1 2
#else
#define L0 0
#define L1 1
#endif
// This struct should be allocate in SIO_Type in the future...
typedef struct {
int Type;
int Ptr;
/* Gamepad fields */
int PadEnd;
void (*Joy_PollBack)(void);
void (*Joy_Vibrate)(int);
char Buf[16];
/* Memory card fields */
char MemBuf[256];
union {
UINT8 l[4];
UINT32 hl;
} Addr;
int EndFlg,Crc;
char *CardName;
char MemoryCard[128*1024];
} pad_type;
static pad_type *flx=NULL;
static pad_type pad[2];
static int nflx=0;
static char cd1[] = {"slot1"};
static char cd2[] = {"slot2"};
static char memcdpath[] = { "memcards\\" };
static int MC_Event();
static int MC_VSync();
int PAD_Init(SIO_Type *sio)
{
int f,x;
char buf[80];
// Prepare the struct
memset(pad,0,sizeof(pad));
strcpy(buf,memcdpath);
if (FPSEIni.Mcd1Name != NULL) strcat(buf,FPSEIni.Mcd1Name);
else strcat(buf,cd1);
pad[0].CardName = strdup(buf);
strcpy(buf,memcdpath);
if (FPSEIni.Mcd2Name != NULL) strcat(buf,FPSEIni.Mcd2Name);
else strcat(buf,cd2);
pad[1].CardName = strdup(buf);
// GamePad header
pad[0].Joy_PollBack = JOY0_Poll;
pad[0].Joy_Vibrate = JOY0_Vibrate;
pad[0].PadEnd = JOY0_InitHeader(pad[0].Buf);
pad[1].Joy_PollBack = JOY1_Poll;
pad[1].Joy_Vibrate = JOY1_Vibrate;
pad[1].PadEnd = JOY1_InitHeader(pad[1].Buf);
for (x=0;x<2;x++)
{
// Memory card header
pad[x].MemBuf[2] = 0x5A;
pad[x].MemBuf[3] = 0x5D;
// Load memory card
f = open(pad[x].CardName, O_RDONLY|O_BINARY);
if (f!=-1)
{
read(f,pad[x].MemoryCard,128*1024);
close(f);
}
}
// Handlers
EventCallBack[INT_SIO0] = MC_Event;
VSyncCallBack[INT_SIO0] = MC_VSync;
// Times to wait before irq
sio->IrqSrc = SIO_IRQ_ASYNC;
sio->IrqFlags = 0x00000003;
return FPSE_OK;
}
void PAD_Close(SIO_Type *sio)
{
free(pad[0].CardName);
free(pad[1].CardName);
JOY0_Close();
JOY1_Close();
}
void PAD_WriteData(SIO_Type *sio)
{
UINT8 *buf = sio->TxBuf;
int v;
UINT8 crc;
if (flx == NULL) return;
if (flx->Ptr == 0)
{
switch (*buf) {
case 0x01:
flx->Type = KPAD; flx->Ptr = 1;
sio->IrqSrc = SIO_IRQ_ASYNC;
sio->IrqFlags = 0x00000003;
break;
case 0x81:
flx->Type = KMEM; flx->Ptr = 1;
sio->IrqSrc = SIO_IRQ_VSYNC;
if (compile)
sio->IrqFlags = 0x00000001;
else
sio->IrqFlags = 0x00000002;
break;
default: break;
}
ACKPAD
sio_async(sio,flx->Buf,1);
NACKPAD
return;
}
if (flx->Type == KPAD)
{
if (flx->Ptr == 1)
{
if ((*buf & 0x40) != 0x40)
{
ACKPAD
sio_async(sio,flx->Buf,1);
NACKPAD
flx->Ptr = 0;
return;
}
else flx->Joy_PollBack();
} else flx->Joy_Vibrate(*buf);
if (flx->Ptr < flx->PadEnd-1) ACKPAD
sio_async(sio,flx->Buf + flx->Ptr,1);
NACKPAD
if (++flx->Ptr >= flx->PadEnd) flx->Ptr = 0;
return;
}
if ((flx->Type & 0x7F) == KMEM)
{
if (flx->Ptr == 1)
{
switch (*buf) {
case 'R':
flx->Type |= READ_CARD;
flx->EndFlg = 140;
break;
case 'W':
flx->EndFlg = 138;
break;
default:
flx->Ptr = 0;
return;
}
}
if (flx->Type & READ_CARD)
{
switch (flx->Ptr) {
case 4:
flx->Addr.l[L1] = *buf;
flx->MemBuf[5] = *buf;
flx->MemBuf[6] = 0x5C;
flx->MemBuf[7] = 0x5D;
flx->MemBuf[8] = *buf;
break;
case 5:
flx->Addr.l[L0] = *buf;
flx->MemBuf[9] = *buf;
memcpy(flx->MemBuf+10,
flx->MemoryCard+flx->Addr.hl*128,
128);
crc = 0; // pad[flx].Addr.l[0] ^ pad[flx].Addr.l[1];
for (v=8;v<128+10;v++)
crc ^= flx->MemBuf[v];
flx->MemBuf[v] = crc;
flx->MemBuf[v+1] = 0x47;
break;
}
}
else {
switch (flx->Ptr) {
case 4:
flx->Addr.l[L1] = *buf;
flx->MemBuf[135] = 0x5C;
flx->MemBuf[136] = 0x5D;
flx->MemBuf[137] = 0x47;
break;
case 5:
flx->Addr.l[L0] = *buf;
flx->Crc = 0; // flx->Addr.l[0] ^ flx->Addr.l[1];
break;
case 134:
printf("caculated crc=%02x\n",flx->Crc);
if (*buf != flx->Crc)
{
flx->MemBuf[137] = 0x4E;
break;
}
memcpy(flx->MemoryCard+flx->Addr.hl*128,
flx->MemBuf+7,128);
}
if (flx->Ptr > 3 &&
flx->Ptr < 134)
{
flx->MemBuf[flx->Ptr+1] = *buf;
flx->Crc ^= *buf;
}
}
if (flx->Ptr < flx->EndFlg) ACKPAD
sio_async(sio,flx->MemBuf + flx->Ptr,1);
NACKPAD
if (++flx->Ptr >= flx->EndFlg) flx->Ptr = 0;
// pad[flx].ptr = 0;
// return;
}
}
void PAD_UpdateStatus(SIO_Type *sio)
{
if (!(sio->Ctrl.Control16 & 2)) {
pad[0].Ptr = pad[1].Ptr = 0;
VSync_Register &= ~(1<<INT_SIO0);
Event_Register &= ~(1<<INT_SIO0);
flx = NULL;
return;
}
if (sio->Ctrl.Control16 & B13) nflx = 1;
else nflx = 0;
flx = pad + nflx;
}
static int MC_Event()
{
VSync_Register &= ~(1<<INT_SIO0);
return 1;
}
static int MC_VSync()
{
Event_Register &= ~(1<<INT_SIO0);
return 1;
}